# 基于sklearn共享单车租赁线性回归预测

import pandas as pd
dataset = pd.read_csv('./bike+sharing+dataset/day.csv', sep=',')
X=dataset.drop(['cnt', 'instant', 'dteday'],axis=1)
y = dataset['cnt']
categorical_features = ['season', 'yr', 'mnth', 'holiday', 'weekday', 'workingday', 'weathersit']
'''
● instant：记录索引
● dteday：日期
● season：季节（1: 春季，2: 夏季，3: 秋季，4: 冬季）
● yr：年份（0: 2011，1: 2012）
● mnth：月份（1 到 12）
● hr：小时（0 到 23）【day.csv中没有此字段】
● holiday：天气是否是假日
● weekday：星期几
● workingday：如果一天既不是周末也不是假日，则为1，否则为0。
● weathersit：天气状况
  ○ 1: 晴天，少云，局部多云，局部多云
  ○ 2: 薄雾 + 多云，薄雾 + 断云，薄雾 + 少云，薄雾
  ○ 3: 小雪，小雨 + 雷暴 + 散云，小雨 + 散云
  ○ 4: 大雨 + 冰块 + 雷暴 + 薄雾，雪 + 雾
● temp：摄氏度中的归一化温度。值被除以41（最大值）
● atemp：摄氏度中的归一化体感温度。值被除以50（最大值）
● hum：归一化湿度。值被除以100（最大值）
● windspeed：归一化风速。值被除以67（最大值）
● casual：休闲用户数量
● registered：注册用户数量
● cnt：总租赁自行车数量，包括休闲用户和注册用户
'''
X_encoded = pd.get_dummies(X, columns=categorical_features)
train_ratio = 0.8
X_train = X_encoded[:int(train_ratio * len(dataset))]
X_test = X_encoded[int(train_ratio * len(dataset)):]
y_train = y[:int(train_ratio * len(dataset))]
y_test = y[int(train_ratio * len(dataset)):]

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

from sklearn.linear_model import LinearRegression
linear_reg_model=LinearRegression()

linear_reg_model.fit(X_train_scaled,y_train)

# 测试
y_pred=linear_reg_model.predict(X_test_scaled)
from sklearn.metrics import mean_squared_error
mse=mean_squared_error(y_test,y_pred)
from sklearn.metrics import r2_score
#计算R-squared值(决定系数),它表示模型对目标变量变异的解释程度,取值范围在0到1之间,越接近1模型拟合效果越好
r2=r2_score(y_test,y_pred)
print(f'测试集损失: {mse}')
print(f'R-squared: {r2}')

import matplotlib.pyplot as plt
plt.figure(0)
plt.scatter(y_test, y_pred)
plt.xlabel('Actual Values')
plt.ylabel('Predicted Values')
plt.title('Actual vs Predicted Values in Linear Regression')
sorted_indices = X_test.index.argsort()

y_test_sorted = y_test.iloc[sorted_indices]
# 根据排序后的索引获取对应的预测值，并转换为pandas的Series类型
y_pred_sorted = pd.Series(y_pred).iloc[sorted_indices]

# 绘制实际值和预测值的曲线
# 创建第二个图形
plt.figure(1)
# 绘制实际值的曲线，用圆形标记，添加标签
plt.plot(y_test_sorted.values, label='Actual Values', marker='o')
# 绘制预测值的曲线，用叉号标记，添加标签
plt.plot(y_pred_sorted.values, label='Predicted Values', marker='x')
plt.xlabel('Sample Index (Sorted)')
plt.ylabel('Values')
plt.title('Actual vs Predicted Values in Linear Regression')
plt.legend()
# 显示绘制的图形，使图形窗口弹出展示结果
plt.show()